/*
 * Copyright © 2017 Cask Data, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

import React, {PropTypes, Component} from 'react';
import {objectQuery} from 'services/helpers';
import isNil from 'lodash/isNil';
import T from 'i18n-react';
import {MyProgramApi} from 'api/program';
import NamespaceStore from 'services/NamespaceStore';
import {convertProgramToApi} from 'services/program-api-converter';
import ViewSwitch from 'components/ViewSwitch';
import ProgramCards from 'components/ProgramCards';
import ProgramTable from 'components/ProgramTable';
import isEmpty from 'lodash/isEmpty';
require('./ProgramTab.scss');

export default class ProgramsTab extends Component {
  constructor(props) {
    super(props);
    this.state = {
      entity: this.props.entity,
      runningPrograms: []
    };
    this.statusSubscriptions = [];
    if (
      !isNil(this.props.entity) &&
      !isEmpty(this.props.entity)
    ) {
      this.setRunningPrograms();
    }
  }
  componentWillReceiveProps(nextProps) {
    let entitiesMatch = objectQuery(nextProps, 'entity', 'name') === objectQuery(this.props, 'entity', 'name');
    if (!entitiesMatch) {
      this.setState({
        entity: nextProps.entity,
        runningPrograms: []
      });
      this.statusSubscriptions.forEach(sub => sub.dispose());
      this.setRunningPrograms();
    }
  }
  componentWillUnmount() {
    this.statusSubscriptions.forEach(sub => sub.dispose());
  }
  setRunningPrograms() {
    let namespace = NamespaceStore.getState().selectedNamespace;
    this.state
        .entity
        .programs
        .forEach(program => {
          let params = {
            namespace,
            appId: program.app,
            programType: convertProgramToApi(program.type),
            programId: program.id
          };
          let subscription =  MyProgramApi
            .pollRuns(params)
            .combineLatest(MyProgramApi.pollStatus(params))
            .subscribe(res => {
              let runningPrograms = this.state.runningPrograms;
              let programState = runningPrograms.filter(prog => prog.name === program.id && prog.app === program.app);
              if (programState.length) {
                runningPrograms = runningPrograms.filter(prog => prog.name !== program.id || (prog.name === program.id && prog.app !== program.app));
              }
              runningPrograms.push(Object.assign({}, !isEmpty(programState) ? programState[0] : {}, {
                latestRun: objectQuery(res, 0, 0) || {},
                status: res[1].status === 'RUNNING' ? 1 : 0,
                backendStatus: res[1].status,
                name: program.id,
                app: program.app
              }));
              this.setState({
                runningPrograms
              });
            });
          this.statusSubscriptions.push(subscription);
        });
  }
  render() {
    let runningProgramsCount = 0;
    let programsForTable = this.state.entity.programs;
    if (this.state.runningPrograms.length) {
      runningProgramsCount = this.state
        .runningPrograms
        .map(runningProgram => runningProgram.status)
        .reduce((prev, curr) => prev + curr);
      programsForTable = this.state.entity.programs.map(program => {
        let matchedProg = this.state.runningPrograms.find(prog => prog.name === program.id && prog.app === program.app) || null;
        return !matchedProg ?
          program
        :
          Object.assign({}, program, {
            status: matchedProg.backendStatus,
            latestRun: matchedProg.latestRun
          });
      });
    }
    if (!isNil(this.state.entity)) {
      if (this.state.entity.programs.length) {
        let title = T.translate('features.Overview.ProgramTab.title', {appId: this.state.entity.name});

        if (['dataset', 'stream'].indexOf(this.state.entity.type) !== -1) {
          title = T.translate('features.Overview.ProgramTab.altTitle', {
            entityId: this.state.entity.id,
            entityType: this.state.entity.type
          });
        }

        return (
          <div className="program-tab clearfix">
            <div className="message-section float-xs-left">
              <strong> {title} </strong>
              <div>{T.translate('features.Overview.ProgramTab.runningProgramLabel', {programCount: runningProgramsCount})}</div>
            </div>
            <ViewSwitch>
              <ProgramCards programs={this.state.entity.programs} />
              <ProgramTable programs={programsForTable} />
            </ViewSwitch>
          </div>
        );
      } else {
        return (
          <div className="program-tab clearfix">
            <i>{T.translate('features.Overview.ProgramTab.emptyMessage')}</i>
          </div>
        );
      }
    }
    return null;
  }
}
ProgramsTab.defaultProps = {
  entity: {
    programs: []
  }
};
ProgramsTab.propTypes = {
  entity: PropTypes.arrayOf(PropTypes.shape({
    id: PropTypes.string,
    programs: PropTypes.arrayOf(PropTypes.shape({
      app: PropTypes.string,
      id: PropTypes.string,
      type: PropTypes.string
    })),
    type: PropTypes.string
  }))
};
